package com.abel.bigwater.tlv.model

import io.netty.buffer.ByteBuf
import java.nio.charset.Charset
import java.util.*
import javax.swing.plaf.basic.BasicEditorPaneUI

data class TlvData1Base(
        var imsi: String? = null,
        var devType: Short = 1,
        var devStatus: MeterStatusParam = MeterStatusParam.T0UnRegistered,
        var meterCode: String? = null,
        var termClock: Date? = null,
        var termRun: Int = 0,
        var termVersion: Short = 1) : TlvData(tag = BaseParam.TAG) {

    override fun finalLen(): Int {
        TODO()
    }

    override fun fill(buf: ByteBuf): ByteBuf {
        if (length == 0) finalLen()

        with(buf.alloc().buffer()) {
            writeByte(tag.toInt())
            writeShort(length)

            if (imsi?.length ?: 0 >= 15) {
                val ba = imsi!!.take(15).toByteArray(Charsets.US_ASCII)
                if (ba.size != imsi!!.length) {
                    throw IllegalArgumentException("IMSI should be ASCII: ${imsi}")
                }

                // id-value, same as the following...
                writeByte(BaseParam.T0IMSI.id.toInt())
                writeBytes(ba)
            }

            writeByte(BaseParam.T1DevType.id.toInt())
            writeByte(devType.toInt())

            writeByte(BaseParam.T2Status.id.toInt())
            writeByte(devStatus.resultCode)

            if (meterCode?.length ?: 0 >= 14) {
                writeByte(BaseParam.T3MeterCode.id.toInt())
                writeBytes(TlvHelper.toBcdArray(meterCode!!.take(14)))
            }

            kotlin.run {
                val ba = ByteArray(6)
                TlvHelper.fillTimestamp(ba, termClock ?: Date())
                writeByte(BaseParam.T4TermClock.id.toInt())
                writeBytes(ba)
            }

            writeByte(BaseParam.T5TermRun.id.toInt())
            writeShort(termRun)

            writeByte(BaseParam.T6TermVersion.id.toInt())
            writeByte(termVersion.toInt())

            // write to passed-in buffer in whole.
            buf.writeBytes(this)
        }

        return buf
    }

    /**
     * dedicated buffer. so just read it directly.
     */
    override fun parse(buf: ByteBuf): ByteBuf {
        try {
            super.parse(buf)
        } catch (ex: TlvException) {
            log.error("BAD buffer for base: ${ex.message}", ex)
        }

        for (p1 in pieceList.orEmpty()) {
            when (p1.id) {
                BaseParam.T0IMSI.id -> imsi = String(p1.value!!, Charset.forName("ASCII"))
                BaseParam.T1DevType.id -> devType = p1.readByte()
                BaseParam.T2Status.id -> devStatus =
                        MeterStatusParam.valueMap[p1.value!![0].toInt()] ?: MeterStatusParam.T2Other

                BaseParam.T3MeterCode.id -> meterCode = TlvHelper.toBcdString(p1.value!!)
                BaseParam.T4TermClock.id -> termClock = TlvHelper.toTimestamp(p1.value!!)
                BaseParam.T5TermRun.id -> termRun = p1.readShort().toInt()
                BaseParam.T6TermVersion.id -> termVersion = p1.readByte()
                else -> log.error("UNKnown piece: ${p1.id}")
            }
        }

        return buf
    }
}